"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.emit = exports.Emit = exports.EventEmitter = void 0;
class EventEmitter {
    constructor() {
        this.callbacks = {};
        this.fn_map = new WeakMap();
        this.fire = this.emit;
    }
    on(eventName, callback) {
        if (!this.callbacks[eventName]) {
            this.callbacks[eventName] = [];
        }
        this.callbacks[eventName].push(callback);
        return () => this.off(eventName, callback);
    }
    off(eventName, callback) {
        var _a;
        if (!((_a = this.callbacks[eventName]) === null || _a === void 0 ? void 0 : _a.length)) {
            return;
        }
        if (callback) {
            this.callbacks[eventName] = this.callbacks[eventName].filter((fn) => fn !== callback && fn !== this.fn_map.get(callback));
            this.fn_map.delete(callback);
        }
        else {
            this.callbacks[eventName] = [];
        }
    }
    once(eventName, callback) {
        const fn = () => {
            callback.apply(this, [...arguments]);
            this.off(eventName, callback);
        };
        this.fn_map.set(callback, fn);
        return this.on(eventName, fn);
    }
    _call(ev, ...args) {
        const fns = this.callbacks[ev];
        fns && fns.forEach((fn) => fn(...args));
    }
    emit(eventName, ...args) {
        const scopes = eventName.split(/\./);
        this._call(eventName, ...args);
        let scope = scopes.slice(0, -1);
        while (scope.length) {
            this._call(scope.join('.') + '.*', ...args);
            scope.pop();
        }
        this._call('*', ...args);
    }
}
exports.EventEmitter = EventEmitter;
exports.Emit = EventEmitter;
const emit = () => new EventEmitter();
exports.emit = emit;
